Level 0 | Level 1 | Level 2 | Level 3 | Level 4 |
Level 5 | Level 6 | Level 7 | Level 8 | Level 9 |
Level 10 | Level 11 | Level 12 | Level 13 | Level 14 |
LEVEL 7 Nintendo Wrecking Crew
You can use 2 methods in ripping this game if you want. nes2nsf or using Nesten to dump the 32KB bank. If you use nes2nsf to
rip the bank then you have to remove the header in order to disassemble, and you have to change the origin to $C000 in the
asm.bat file.
Next you want to find the entry to the play address. This is the easy part of the rip and you should find it quick. I found
the entry to the play by using the stack. Here is the code to the play routine.
$F2E6> A9 C0: LDA #$c0 ; $F2E8> 8D 1740: STA $4017 ; [NES] Joypad & I/O port for port #2 $F2EB> A5 F0: LDA $F0 ; $F2ED> 4A: LSR A ; $F2EE> B0 F3: BCS $F2E3 ; $F2F0> A5 F1: LDA $F1 ; $F2F2> 4A: LSR A ; $F2F3> B0 CA: BCS $F2BF ; $F2F5> AD FD07: LDA $07FD ; $F2F8> D0 18: BNE $F312 ; $F2FA> 20 DCF3: JSR $F3DC ; $F2FD> 20 00F6: JSR $F600 ; $F300> 20 21F7: JSR $F721 ; $F303> 20 7EF8: JSR $F87E ; $F306> 20 3EF2: JSR $F23E ; $F309> A9 00: LDA #$00 ; $F30B> 85 F0: STA $F0 ; $F30D> 85 F1: STA $F1 ; $F30F> 85 F2: STA $F2 ; $F311> 60: RTS ;
This is the entire play code nice and neat. You see it starts out with the following code.
$F2E6> A9 C0: LDA #$c0 ; $F2E8> 8D 1740: STA $4017
This is what most old Nintendo games do, except that most of the others also write to $4015. You can sometimes find the play
code and not debug for it at all.
The real problem with this game is that the driver doesn't have an init code and you have to design one. So here is how it
works. You go to a level and it loads a tune number into a certain address, once the play address is called then the code
checks the address to see if the number has changed and if it has then the play address updates the hardware and the tune.
So you want to figure out how to design an init routine. This is not one of the more easy things to do. First of all you need
to find out what memory addresses are used for the tune. You won't find these using a memory editor because the addresses
are updated all the time like crazy, everytime the NMI is triggered. So look at the bottom of the play routine and notice
this code here.
$F309> A9 00: LDA #$00 ; $F30B> 85 F0: STA $F0 ; $F30D> 85 F1: STA $F1 ; $F30F> 85 F2: STA $F2 ; $F311> 60: RTS
These are your memory addresses you are looking for. Yes, all the old Nintendo games are the same way and you can find these
addresses right at the end of the play code. Simple as that. What you do is make a tune arrangement code routine and start
with one address at a time and find out what the tunes are. You will find out that one of them is for looping tunes, the
next is for non looping tunes and the last is for sound effects. Write down the number for each for tune and convert to hex.
You should make the following code to figure out what the tune numbers are and change the memory address write to the next
one when done.
85 F1: STA $F0 60: RTS
So you find out F0 is for sound effects, F1 is for most non looping tunes and a couple looping and some sound effects. F2 is
all sound effects and these are better then F0.
What you do next is look for some code in the game before making an init routine. Using read and write break points in a
emulator debugger you eventually end up with this code. Ignore any reads and writes in the game play code. Only within the
sound driver range.
$F87E> AD DB07: LDA $07DB ; $F881> 4A: LSR A ; $F882> B0 30: BCS $F8B4 ; $F884> 4A: LSR A ; $F885> B0 22: BCS $F8A9 ; $F887> A5 F1: LDA $F1 ; $F889> 4A: LSR A ; $F88A> 4A: LSR A ; $F88B> B0 EA: BCS $F877 ; $F88D> 4A: LSR A ; $F88E> B0 12: BCS $F8A2 ; $F890> 4A: LSR A ; $F891> B0 5A: BCS $F8ED ; $F893> 4A: LSR A ; $F894> B0 3C: BCS $F8D2 ; $F896> 4A: LSR A ; $F897> B0 27: BCS $F8C0 ; $F899> AD F307: LDA $07F3 ; $F89C> D0 01: BNE $F89F ; $F89E> 60: RTS ;
This is part of the play code and is rather complicated. This determines when the tune address is changed for F1. Also you
note the address $07DB which you must also use in your init code because you must initialize this address to work with this
code here.
Now is the time to design some code for the tunes and all the addresses must be in the same code routine. If you use one
address to play a tune you must silence the others. You do this by arranging the data. So here is the code you can use that
works for multiple memory addresses.
ASL ASL TAX LDA $FFA0,X STA $F0 LDA $FFA1,X STA $F1 LDA $FFA2,X STA $F2 LDA $FFA3,X STA $07DB RTS .db see rip for data ordering
This code is set up like the actual rip with the addresses pointing to the tune index. Remember that when you have a setup
like this you would for example load a byte into $F0 and silence the rest out to play a tune. Then you would play the next
tune and it would silence $F0 and load a tune byte into $F1 and so on. In order to use the code this way you would have to
arrange the data and this takes some practice to get it right. For instance 00,08,00,00,00 this silences F0,and F2 and loads
F1 with a tune. This is also based on what the contents of the X register is as well. Look at the actual rip and check out
the code and data ordering and play with them some. The rip out there is not ordered right anyway, you could fix that up if
you wanted to.
This is the end of the level and you learned how to deal with a complex situation where you use more then one address for
the tunes. Also that this is the way older Nintendo games store their music driver. You could do many Nintendo games this way.
TEST: ------
Rip Urban Champion. This rip will require a bootstrap code along with using 3 memory addresses, you must silence one of them.
I will only tell you this. The tunes are 10,20,08,04,02,40,80 and the sound effects you have to find. This test requires
methods from a couple of different levels so have fun. You must use this level's method in order to get the sound effects
with the tunes. Some sound effects are in the tune address. This NSF hasn't been ripped yet.